﻿/******************************************************************************
* File description: animationController_Shifting.h
* Function: 转靶动画Controller，基于State的状态，根据时间计算当前动画的过渡状态，并提供获取当前状态的接口
* Current Version: 1.0.0
* Author: JNN
* Date: 2025-07-01
*  -----
*  Copyright by 博坤生物 .
 *****************************************************************************/

#include "animationController_Shifting.h"

/** @brief 构造函数 */
AnimationController_Shifting::AnimationController_Shifting(AnimationState_Shifting* state)
{
    startTimer();
    _state = state;
    reset();
    connect(_state, SIGNAL(reset()), this, SLOT(reset()));
    refreshBarPosiByMachineType(0);
}

/** @brief 复位 */
void AnimationController_Shifting::reset(){

    _barPosi = 0;               // 开盖和取靶那个杆的位置，0在最左，1在最右
    _barState = 0;
    _capCranePosi = 0;          // 上下位置 0最上面 1最下面
    _capCraneState = 0;         // 状态 0灰 1运行 -1故障
    _capCraneClampState = 0;         // 1夹紧 0松开
    _targetCranePosi = 0;       // 上下位置 0最上面 1最下面
    _targetCraneState = 0;      // 状态
    _radioBarPosi = 0;         // 活检 - 上下位置 0最上面 1最下面
    _targetBottleCapAngle = 0;   // 瓶盖在哪 0在罐子里 1在取盖器上
    _targetBottleCapState = 0;
    _targetBottleBodyState = 0;
    _clampPosi = 0;         // 1夹紧 0松开
    _clampState = 0;
    _feedPortState = 0;
    _bafflePosi = 1;        // 1挡住 0不挡
    _baffleState = 0;
    _productBottleState = 0;
    _bulbState = {0, 0, 0, 0};
    _suckAngle = 0;
}

void AnimationController_Shifting::refreshBarPosiByMachineType(int type){
    if(type == 1){
        BAR_POSI_ORI   = 0.000;        // 原点
        BAR_POSI_CAP   = 0.525;        // 开盖（开盖器对准靶材罐
        BAR_POSI_TAR1  = 0.056;        // 吸靶（吸盘对准靶材罐
        BAR_POSI_TAR2  = 0.525;        // 放靶（吸盘对准溶靶罐
        BAR_POSI_RADIO = 0.770;        // 活检（吸盘对准活检

    }else {
        BAR_POSI_ORI   = 0.000;        // 原点
        BAR_POSI_CAP   = 0.696;        // 开盖（开盖器对准靶材罐
        BAR_POSI_TAR1  = 0.355;        // 吸靶（吸盘对准靶材罐
        BAR_POSI_TAR2  = 0.696;        // 放靶（吸盘对准溶靶罐
        BAR_POSI_RADIO = 0.355;        // 活检（吸盘对准活检
    }
}


/** @brief QML调用请求动画信息
 *  @return QVariantMap 返回每个组件的位置 */
QVariantMap AnimationController_Shifting::requestInfo(){

    QVariantMap res;

    // 开盖器和吸靶器
    res["BarPosi"] = _barPosi;
    res["BarState"] = _barState;
    res["CapCranePosi"] = _capCranePosi;
    res["CapCraneState"] = _state->_capCraneState==-1 ? -1 : _capCraneState;
    res["TargetCranePosi"] = _state->_targetCraneState==-1 ? -1 : _targetCranePosi;
    res["TargetCraneState"] = _targetCraneState;
    res["SuckAngle"] = _suckAngle;

    // 下面的信息
    res["TargetBottleCapAngle"] = _targetBottleCapAngle;
    res["TargetBottleCapState"] = _targetBottleCapState;
    res["TargetBottleBodyState"] = _targetBottleBodyState;
    res["ClampPosi"] = _clampPosi;
    res["ClampState"] = _clampState;
    res["FeedPortState"] = _feedPortState;
    res["BafflePosi"] = _bafflePosi;
    res["BaffleState"] = _baffleState;
    res["CapCraneClampState"] = _capCraneClampState;
    res["RadioBarPosi"] = _radioBarPosi;


    // 右边的
    res["ProductBottleState"] = _productBottleState;
    res["BlowTargetState"] = _state->_blowTargetState;

    res["DrawTargetBottle"] = StaticProperties::releasseTargetStatus["0"]=="无" ? false : true;

    QVariantList bulbState;
    for(int i = 0; i < 4; i ++){
        if(StaticProperties::pipeStatus.size() <= i){
            bulbState.push_back(-1);
        }else{
            bulbState.push_back(StaticProperties::pipeStatus[QString::number(i)]);
        }
    }
    res["BulbState"]     = bulbState;


    res["PumpState"] = _state->_peristalticPump;

    return res;
}

/** @brief 开启动画定时器（每帧调用） */
void AnimationController_Shifting::startTimer(){

    _timer = new QTimer();
    _timer->setInterval(_interval);
    connect(_timer, SIGNAL(timeout()), this, SLOT(updateState()));
    _timer->start();

}

/** @brief 停止定时器 */
void AnimationController_Shifting::stopTimer(){

    if(_timer){
        _timer->stop();
        delete _timer;
    }
}

/** @brief TP */
void AnimationController_Shifting::teleportX(int idx){

}
void AnimationController_Shifting::teleportZ(int idx){

}

/** @brief 更新动画帧状态 */
void AnimationController_Shifting::updateState(double interval){

    // shifting好像没有需要用到动态interval的方式……
    double speedBase;
    if(interval == -1){     // 默认模式
        speedBase = _interval / 1000.0;
    }else{
        speedBase = 1;
    }

    double costTime;

    // 挡板
    costTime = 1;
    if(_bafflePosi != _state->_bafflePosi){
        _baffleState = 1;
        if(_bafflePosi > _state->_bafflePosi){
            _bafflePosi = std::max(_bafflePosi-speedBase/costTime, (double)_state->_bafflePosi);
        }else{
            _bafflePosi = std::min(_bafflePosi+speedBase/costTime, (double)_state->_bafflePosi);
        }
    }else{
        _baffleState = 0;
    }
    // 夹爪
    costTime = 0.6;
    if(_clampPosi != _state->_clampPosi){
        _clampState = 1;
        if(_clampPosi > _state->_clampPosi){
            _clampPosi = std::max(_clampPosi-speedBase/costTime, (double)_state->_clampPosi);
        }else{
            _clampPosi = std::min(_clampPosi+speedBase/costTime, (double)_state->_clampPosi);
        }
    }else{
        _clampState = 0;
    }
    // 活检
    costTime = 2;
    if(_radioBarPosi != _state->_radioBarPosi){
        if(_radioBarPosi > _state->_radioBarPosi){
            _radioBarPosi = std::max(_radioBarPosi-speedBase/costTime, (double)_state->_radioBarPosi);
        }else{
            _radioBarPosi = std::min(_radioBarPosi+speedBase/costTime, (double)_state->_radioBarPosi);
        }
    }else{
        _clampState = 0;
    }


    // Bar的队列
    // 当前为空时，判断还有没有待执行的步骤
    if(_curBarOp == AS_S::EMPTY){
        if(_state->_barOperation.size() > 0){


            // 如果夹爪在下面要先运动到上面，插一个步骤进去
            if((_state->_barOperation.head() == AS_S::MOV_CAP && _barPosi != BAR_POSI_CAP) ||
                    (_state->_barOperation.head() == AS_S::MOV_ORIGIN && _barPosi != BAR_POSI_ORI) ||
                    (_state->_barOperation.head() == AS_S::MOV_TARGET1 && _barPosi != BAR_POSI_TAR1) ||
                    (_state->_barOperation.head() == AS_S::MOV_TARGET2 && _barPosi != BAR_POSI_TAR2) ||
                    (_state->_barOperation.head() == AS_S::MOV_RADIO && _barPosi != BAR_POSI_RADIO)){
                if(_capCranePosi == 1){
                    _curBarOp = AS_S::UP_CAP;
                }else{
                    _curBarOp = _state->_barOperation.dequeue();
                }
            }else{
                _curBarOp = _state->_barOperation.dequeue();
            }

        }
    }
    // 开始执行
    switch (_curBarOp) {
    // - 移动到原点s
    case AS_S::MOV_ORIGIN:{
        costTime = 2;
        if(_barPosi != BAR_POSI_ORI){
            _barState = 1;
            if(_barPosi > BAR_POSI_ORI){
                _barPosi = std::max(_barPosi-speedBase/costTime, BAR_POSI_ORI);
            }else{
                _barPosi = std::min(_barPosi+speedBase/costTime, BAR_POSI_ORI);
            }
        }else{
            _barState = 0;
            _curBarOp = AS_S::EMPTY;
        }
    }   break;
    // - 移动到开盖
    case AS_S::MOV_CAP:{
        costTime = 2;
        if(_barPosi != BAR_POSI_CAP){
            _barState = 1;
            if(_barPosi > BAR_POSI_CAP){
                _barPosi = std::max(_barPosi-speedBase/costTime, BAR_POSI_CAP);
            }else{
                _barPosi = std::min(_barPosi+speedBase/costTime, BAR_POSI_CAP);
            }
        }else{
            _barState = 0;
            _curBarOp = AS_S::EMPTY;
        }
    }   break;
    // - 移动到吸靶
    case AS_S::MOV_TARGET1:{
        costTime = 2;
        if(_barPosi != BAR_POSI_TAR1){
            _barState = 1;
            if(_barPosi > BAR_POSI_TAR1){
                _barPosi = std::max(_barPosi-speedBase/costTime, BAR_POSI_TAR1);
            }else{
                _barPosi = std::min(_barPosi+speedBase/costTime, BAR_POSI_TAR1);
            }
        }else{
            _barState = 0;
            _curBarOp = AS_S::EMPTY;
        }
    }   break;
    // - 移动到放靶
    case AS_S::MOV_TARGET2:{
        costTime = 2;
        if(_barPosi != BAR_POSI_TAR2){
            _barState = 1;
            if(_barPosi > BAR_POSI_TAR2){
                _barPosi = std::max(_barPosi-speedBase/costTime, BAR_POSI_TAR2);
            }else{
                _barPosi = std::min(_barPosi+speedBase/costTime, BAR_POSI_TAR2);
            }
        }else{
            _barState = 0;
            _curBarOp = AS_S::EMPTY;
        }
    }   break;
    // - 移动到活检
    case AS_S::MOV_RADIO: {
        costTime = 2;
        if(_barPosi != BAR_POSI_RADIO){
            _barState = 1;
            if(_barPosi > BAR_POSI_RADIO){
                _barPosi = std::max(_barPosi-speedBase/costTime, BAR_POSI_RADIO);
            }else{
                _barPosi = std::min(_barPosi+speedBase/costTime, BAR_POSI_RADIO);
            }
        }else{
            _barState = 0;
            _curBarOp = AS_S::EMPTY;
        }
    } break;
    // - 开盖器下移
    case AS_S::DOWN_CAP:{
        costTime = 1.8;
        if(_capCranePosi != 1){
            _capCraneState = 1;
            if(_capCranePosi > 1){
                _capCranePosi = std::max(_capCranePosi-speedBase/costTime, 1.0);
            }else{
                _capCranePosi = std::min(_capCranePosi+speedBase/costTime, 1.0);
            }
        }else{
            _capCraneState = 0;
            _curBarOp = AS_S::EMPTY;
        }
    }   break;
    // - 开盖器上移
    case AS_S::UP_CAP: {
        costTime = 1.8;
        if(_capCranePosi != 0){
            _capCraneState = 1;
            if(_capCranePosi > 0){
                _capCranePosi = std::max(_capCranePosi-speedBase/costTime, 0.0);
            }else{
                _capCranePosi = std::min(_capCranePosi+speedBase/costTime, 0.0);
            }
        }else{
            _capCraneState = 0;
            _curBarOp = AS_S::EMPTY;
        }
    }   break;
    // - 吸盘下移
    case AS_S::DOWN_TARGET:{
        costTime = 1.2;
        if(_targetCranePosi != 1){
            _targetCraneState = 1;
            if(_targetCranePosi > 1){
                _targetCranePosi = std::max(_targetCranePosi-speedBase/costTime, 1.0);
            }else{
                _targetCranePosi = std::min(_targetCranePosi+speedBase/costTime, 1.0);
            }
        }else{
            _targetCraneState = 0;
            _curBarOp = AS_S::EMPTY;
        }
    }   break;
    // - 吸盘上移
    case AS_S::UP_TARGET:{
        costTime = 1.2;
        if(_targetCranePosi != 0){
            _targetCraneState = 1;
            if(_targetCranePosi > 0){
                _targetCranePosi = std::max(_targetCranePosi-speedBase/costTime, 0.0);
            }else{
                _targetCranePosi = std::min(_targetCranePosi+speedBase/costTime, 0.0);
            }
        }else{
            _targetCraneState = 0;
            _curBarOp = AS_S::EMPTY;
        }
    }   break;
    // 顺时针拧盖(关盖)(1->0)
    case AS_S::ROT_CAP_0_CLOSE: {
        costTime = 8;
        if(_targetBottleCapAngle != 0){
            _targetBottleCapAngle = std::max(_targetBottleCapAngle - speedBase/costTime, 0.0);
        }else{
            _curBarOp = AS_S::EMPTY;
        }
    } break;
    // 逆时针拧盖(开盖)(0->1)
    case AS_S::ROT_CAP_1_OPEN: {
        costTime = 8;
        if(_targetBottleCapAngle != 1){
            _targetBottleCapAngle = std::min(_targetBottleCapAngle + speedBase/costTime, 1.0);
        }else{
            _curBarOp = AS_S::EMPTY;
        }
    }break;
    // 开盖夹爪松开 1->0
    case AS_S::OPEN_CAP_CLAMP: {
        costTime = 0.5;
        if(_capCraneClampState != 0){
            _capCraneClampState = std::max(_capCraneClampState - speedBase/costTime, 0.0);
        }else{
            _curBarOp = AS_S::EMPTY;
        }
    }break;
    // 开盖夹爪夹紧 0->1
    case AS_S::CLOSE_CAP_CLAMP: {
        costTime = 0.5;
        if(_capCraneClampState != 1){
            _capCraneClampState = std::min(_capCraneClampState + speedBase/costTime, 1.0);
        }else{
            _curBarOp = AS_S::EMPTY;
        }
    }break;
    // 转到放靶  0->1  (0->135°)
    case AS_S::ROTATE_TARGET1: {
        costTime = 0.8;
        if(_suckAngle != 0){
            _suckAngle = std::max(_suckAngle - speedBase/costTime, 0.0);
        }else{
            _curBarOp = AS_S::EMPTY;
        }
    }break;
    // 转到活检  1->0  (135°->0)
    case AS_S::ROTATE_RADIO: {
        costTime = 0.8;
        if(_suckAngle != 1){
            _suckAngle = std::min(_suckAngle + speedBase/costTime, 1.0);
        }else{
            _curBarOp = AS_S::EMPTY;
        }
    }
    default:
        break;
    }

}

